/**
 * 依赖库：jQuery/Zepto
 */

;((global, factory) => {
	typeof exports === 'object' && module != 'undefined' ? module.exports = factory() :
	(global.Page = factory())
})(window || global, () => {

	const defaultConfig = {
		droploadOffsert: 0,
		isOpenPromise: false
	}

	class _Page {
		constructor(options) {
			this.options = options;
			this._checkEnv();
			this._ready();
			this._before();
			this._init();
		}
		// 检查接收到的对象
		_checkEnv() {
			const {init} = this.options;

			if(typeof init !== 'function') {
				throw new Error('没有找到init函数！');
			}
			if (!$) {
				throw new Error('缺少依赖：jQuery');
			}
		}
		// methods函数promise化
		_promise(methods) {
			if (!methods || typeof methods !== 'object') {
				return;
			}
			return Object.keys(methods).reduce((finialMethods, key) => {
				finialMethods[key] = function() {
					const args = arguments;
					return new Promise((resolve, reject) => {
						methods[key].call(this, ...args, resolve, reject);
					})
				}.bind(this);
				return finialMethods;
			}, {})
		}
		// 绑定data和方法到实例
		_ready() {
			let {data, methods} = this.options;
			this.data = data || {};
			if (defaultConfig.isOpenPromise) {
				methods = this._promise(methods);
			}
			$.extend(this, methods || {});
		}
		// render方法
		render() {
			const {render} = this.options,
				args = arguments;
			$.isFunction(render) && render.apply(this, args);
			!this.inited && this._bind();
			!this.inited && this._mouted();
		}
		// 初始化前执行函数
		_before() {
			const {before} = this.options;
			$.isFunction(before) && before.call(this);
		}
		// 页面渲染后执行函数
		_mouted() {
			const {mouted} = this.options;
			$.isFunction(mouted) && mouted.call(this);
			this.inited = true;
		}
		// 绑定某一类事件
		_bindEvent(eventType, handlers) {
			const self = this,
				keys = Object.keys(handlers),
				selector = keys.join(',');

			$(document).on(eventType, selector, function (ev) {
				const className = this.className;
				const JClassName = className.match(/(J_[\-\w]+)(\s|$)/)[1];
				const func = handlers['.' + JClassName];

				return $.isFunction(func) && func.call(this, ev, self);
			});
		}
		_bindDropload(dropload) {
			const $doc = $(document),
				$win = $(window),
				windowHeight = $win.height();
			let	isLoading = false,
				stopLoading = (hasMore) => {
					isLoading = !hasMore;
					if (!hasMore) {
						$win.off('scroll');
					}
				};
			$win.on('scroll', (ev) => {
				const containerHeight = $doc.height(),
					scrollTop = $win.scrollTop();
				if (!isLoading && (windowHeight + scrollTop + defaultConfig.droploadOffsert >= containerHeight)) {
					isLoading = true;
					dropload.call(this, stopLoading);
				}
			})
		}
		// 绑定事件函数
		_bind() {
			const {options} = this,
				{dropload} = options;
			Object.keys(options).filter(key => key.indexOf('on') === 0).map(key => {
				this._bindEvent(key.slice(2), options[key]);
			});
			$.isFunction(dropload) && this._bindDropload(dropload);
		}
		// 初始化函数
		_init() {
			const {init} = this.options;
			init.call(this, this.render.bind(this));
		}
		// 暴露出更新数据的函数
		setData(options, deep) {
			if (!$.isPlainObject(options)) {
				return;
			}
			this.data = $.extend(deep, this.data, options);
		}
	}

	return (options, config) => {
		$.extend(defaultConfig, config);
		return new _Page(options);
	}
});
